package DatabaseUpdate;

import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import Watch.DirData;
import Watch.DirDataChanges;

public class DatabaseUpdater implements Runnable
{
	//queue with jobs
	ConcurrentLinkedQueue<DirDataChanges> jobsQueue;
	volatile boolean pause;
	volatile boolean stop;
	
	
	//DirDataChanges dirDataChange = null;
	SessionFactory sessionFactory;
	Session session;
	DirData dirData = new DirData();
	
	public DatabaseUpdater() 
	{
		//create the empty queue
		jobsQueue = new ConcurrentLinkedQueue<DirDataChanges>();
		pause = false;
		stop = false;
	}
	
	@Override
	public void run()
	{
		System.out.println("started to run");
		while(stop == false)
		{
			//get the command from queue
			if(jobsQueue.isEmpty() == false)
			{
				System.out.println("new job!");
				DirDataChanges newChange = jobsQueue.poll();
				//call method for commiting the change
				commitChange(newChange);
			}
			allowPause();	// allow this loop to be paused
		}
	}
	
	public void commitChange(DirDataChanges dirDataChange)
	{
		if(dirDataChange.getChange().equals("Created") == false)
		{
			//open new session with hibernate
			sessionFactory = new Configuration().configure().buildSessionFactory();
			session = sessionFactory.openSession();
			System.out.println("the path is "+(dirDataChange.getPath()).trim());
			//make the query in HQL language according the path
			Query query = session.createQuery("from DirData where pathString = :path");
			query.setParameter("path", (dirDataChange.getPath()).trim());
			
			//get the dirData object from this request
			dirData = (DirData)query.uniqueResult();
		 }
		//call the appropriate method
		//if(dirDataChange.getChange().equals("Created")){ created();	}
		if(dirDataChange.getChange().equals("Deleted")){ deleted(dirDataChange); }
		else if(dirDataChange.getChange().equals("Modified")){ modified(dirDataChange); }
		else if(dirDataChange.getChange().equals("Renamed")){ renamed(dirDataChange); }
		
	}
	
	/*
	 * Method for the case that the file was renamed
	 */
	public void renamed(DirDataChanges dirDataChange)
	{
		//if it was creation
		if(dirData == null)
		{
			System.out.println("CREATING");
			created(dirDataChange);
		}
		else
		{
			//if it was really a change commited
			if(dirDataChange.getNewPath().equals(dirData.getPathString()) == false)
			{
				System.out.println("RENAMING "+dirDataChange.getNewPath()+" old "+dirData.getPathString());
				//because it is a key, we have to remove and then create
				deleted(dirDataChange);
				created(dirDataChange);
			}
		}
	}
	
	public void deleted(DirDataChanges dirDataChange)
	{
		//if it is a tupple
		if(dirData != null)
		{
			session.delete(dirData);
			session.flush();
		}else
		{
			System.out.println("error in delete");
		}
	}
	
	public void modified(DirDataChanges dirDataChange)
	{
		//if it is a tupple
		if(dirData != null)
		{
			dirData.setDateModify(dirDataChange.getDateModify());
			session.update(dirData);
			session.flush();
		}
	}
	
	/**
	 * method for creation of new dir data entry
	 */
	public void created(DirDataChanges dirDataChange)
	{
		 System.out.println("create!!!");
		 //create new dir data object
		 DirData newdirData = new DirData();
		 newdirData.setPathString(dirDataChange.getNewPath());
		 newdirData.setUserName("Anya");
		 newdirData.setTag("");
		 newdirData.setDateModify(new Date());
		 
		 //open new session with hibernate
		 sessionFactory = new Configuration().configure().buildSessionFactory();
		 session = sessionFactory.openSession();
		 
		 //store the new entry
		 UserManager manager = new UserManager(session);
		
		 manager.saveDirData(newdirData);
		 //System.out.println("User saved with ID = "+ dirData.getPathString());
		
		 session.flush();
	}

	/**
	 * Check the pause flag and insert the thread to the waiting if the pause is true
	 */
	protected void allowPause()
	{
		if(pause)
		{
			System.out.format("paused>\n");
			synchronized (this) 
			{
				try 
				{ 
					wait();
				} catch (InterruptedException e) {}
			}
		}
	}
	
	//method for set the pause true
	public void pause(){ pause = true; }
	
	// set the stop true
	public void stop(){ stop = true; }
		
	//change the stop flag to false in order we can continue run
	public void resume() { pause = false; }
	
}
